package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.model.user.UserInfo;
import com.atguigu.tingshu.model.user.UserPaidTrack;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

	@Autowired
	private TrackInfoMapper trackInfoMapper;

	@Autowired
	private AlbumInfoMapper albumInfoMapper;

	@Autowired
	private TrackStatMapper trackStatMapper;

	@Autowired
	private VodService vodService;

	@Autowired
	private UserInfoFeignClient userInfoFeignClient;
	@Override
	public void saveTrackInfo(TrackInfoVo trackInfoVo) {
		//1.新增声音
		TrackInfo trackInfo = new TrackInfo();
		BeanUtils.copyProperties(trackInfoVo, trackInfo);
		//设置主播id
		Long userId = AuthContextHolder.getUserId();
		userId=userId==null ? 1:userId;
		trackInfo.setUserId(userId);
		//查询同一专辑下,编号最大的声音编号
		TrackInfo preTrack = this.getOne(new LambdaQueryWrapper<TrackInfo>()
				.eq(TrackInfo::getAlbumId, trackInfoVo.getAlbumId())
				.orderByDesc(TrackInfo::getOrderNum)
				.last("limit 1")
				.select(TrackInfo::getOrderNum));
		//如果前一个声音为空,则说明当前声音是第一个声音,否则取前一个声音的编号+1
		trackInfo.setOrderNum(preTrack==null ? 1 :preTrack.getOrderNum()+1);
		//根据文件id查询媒体信息
		TrackMediaInfoVo mediaInfoVo = this.vodService.getMediaInfo(trackInfoVo.getMediaFileId());
		if (mediaInfoVo !=null){
			trackInfo.setMediaDuration(new BigDecimal(mediaInfoVo.getDuration()));
			trackInfo.setMediaSize(mediaInfoVo.getSize());
			trackInfo.setMediaType(mediaInfoVo.getType());
			trackInfo.setMediaUrl(mediaInfoVo.getMediaUrl());
		}
		//来源
		trackInfo.setSource(SystemConstant.TRACK_SOURCE_USER);
		trackInfo.setStatus(SystemConstant.TRACK_STATUS_PASS);
		this.save(trackInfo);

		Long trackId = trackInfo.getId();
		//2.更新专辑中的音频数量
		AlbumInfo albumInfo = this.albumInfoMapper.selectById(trackInfoVo.getAlbumId());
		albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount()+1);
		this.albumInfoMapper.updateById(albumInfo);
		//3.初始化音频的统计数据
		initTrackStat(trackId,SystemConstant.TRACK_STAT_PLAY);
		initTrackStat(trackId, SystemConstant.TRACK_STAT_COLLECT);
		initTrackStat(trackId,SystemConstant.TRACK_STAT_PRAISE);
		initTrackStat(trackId, SystemConstant.TRACK_STAT_COMMENT);

	}

	@Override
	public Page<TrackListVo> findUserTrackPage(Integer page, Integer limit, TrackInfoQuery query) {
		//设置主播id
		Long userId = AuthContextHolder.getUserId();
		query.setUserId(userId==null ?1 : userId);
		return trackInfoMapper.findUserTrackPage(new Page<>(page, limit),query);
	}

	@Override
	public void updateTrackInfo(Long trackId, TrackInfoVo trackInfoVo) {
		//根据声音id查询声音
		TrackInfo trackInfo = this.trackInfoMapper.selectById(trackId);
		String mediaFileId = trackInfo.getMediaFileId();
		BeanUtils.copyProperties(trackInfoVo,trackInfo);
		//判断媒体文件是否发生改变
		if (!StringUtils.equals(mediaFileId,trackInfoVo.getMediaFileId())){
			TrackMediaInfoVo mediaInfo = this.vodService.getMediaInfo(trackInfoVo.getMediaFileId());
			trackInfo.setMediaType(mediaInfo.getType());
			trackInfo.setMediaUrl(mediaInfo.getMediaUrl());
			trackInfo.setMediaSize(mediaInfo.getSize());
			trackInfo.setMediaDuration(new BigDecimal(mediaInfo.getDuration()));
		}
		this.trackInfoMapper.updateById(trackInfo);
	}

	@Override
	public void removeTrackInfo(Long trackId) {
		TrackInfo trackInfo = this.getById(trackId);
		//1.删除对应的声音信息
		this.removeById(trackId);
		//2.删除统计信息
		this.trackStatMapper.delete(new LambdaUpdateWrapper<TrackStat>()
				.eq(TrackStat::getTrackId,trackId));
		//3.删除媒体文件
		this.vodService.removeMedia(trackInfo.getMediaFileId());
		//4.更新专辑表中包含声音的数量
		AlbumInfo albumInfo = this.albumInfoMapper.selectById(trackInfo.getAlbumId());
		albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount()-1);
		this.albumInfoMapper.updateById(albumInfo);

	}

	@Override
	public Page<AlbumTrackListVo> findAlbumTrackPage(Long albumId, Integer page, Integer limit) {

		// 根据专辑id分页查询声音
		Page<AlbumTrackListVo> albumTrackListVoPage = this.trackInfoMapper
				.findAlbumTrackPage(new Page<>(page, limit), albumId);
		List<AlbumTrackListVo> albumTrackListVos = null;
		if (albumTrackListVoPage == null || CollectionUtils.isEmpty(albumTrackListVos = albumTrackListVoPage.getRecords())){
			return null;
		}

		// 根据专辑id查询专辑
		AlbumInfo albumInfo = this.albumInfoMapper.selectById(albumId);
		if (albumInfo == null){
			return null;
		}

		// 判断专辑是否是免费专辑，如果是则直接返回分页结果集
		if (SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfo.getPayType())){
			return albumTrackListVoPage;
		}

		// 获取当前页需要付费的声音列表
		List<AlbumTrackListVo> needPaidTracks = albumTrackListVos.stream().filter(albumTrackListVo ->
				albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree()).collect(Collectors.toList());
		// 判断需要付费的声音列表是否为空，如果为空则说明都是免费试听的声音，则直接返回分页结果集
		if (CollectionUtils.isEmpty(needPaidTracks)){
			return albumTrackListVoPage;
		}

		// 获取登录状态
		Long userId = AuthContextHolder.getUserId();
		if (userId == null){ // 如果没有登录，则所有需要付费的声音都要显示付费标签
			needPaidTracks.forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));
		}

		// 根据用户的id查询用户
		Result<UserInfo> userInfoResult = this.userInfoFeignClient.queryUserById(userId);
		Assert.notNull(userInfoResult, "声音的分页查询时，获取用户信息失败！");
		UserInfo userInfo = userInfoResult.getData();
		// 判断专辑是否是vip免费专辑 且 用户是未过期vip用户
		if (SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(albumInfo.getPayType())
				&& userInfo.getIsVip() == 1 && userInfo.getVipExpireTime().after(new Date())){
			return albumTrackListVoPage;
		}

		// 查询是否购买过专辑
		Result<Boolean> isPaidAlbumResult = this.userInfoFeignClient.isPaidAlbum(albumId);
		Assert.notNull(isPaidAlbumResult, "声音的分页查询，获取用户购买专辑记录失败！");
		if (isPaidAlbumResult.getData()){
			return albumTrackListVoPage;
		}

		// 查询当前用户已购买同一专辑下的声音列表
		Result<List<UserPaidTrack>> userPaidTrackResult = this.userInfoFeignClient.queryPaidTracks(albumId);
		Assert.notNull(userPaidTrackResult, "声音的分页查询，获取用户已购买的声音失败！");
		List<UserPaidTrack> userPaidTracks = userPaidTrackResult.getData();
		// 如果用户已购买的声音为空则所有需要付费的声音都需要显示付费标签
		if (CollectionUtils.isEmpty(userPaidTracks)){
			needPaidTracks.forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));
		}
		// 获取已购买的声音id集合
		List<Long> paidTrackIds = userPaidTracks.stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());

		// 遍历需要付费的声音，判断在不在已购买的声音列表中
		needPaidTracks.forEach(albumTrackListVo -> {
			// 不在已购买的声音列表中则显示付费标签
			if (!paidTrackIds.contains(albumTrackListVo.getTrackId())){
				albumTrackListVo.setIsShowPaidMark(true);
			}
		});

		return albumTrackListVoPage;
	}

	@Override
	public TrackStatVo getTrackStatVo(Long trackId) {
		return this.trackInfoMapper.getTrackStatVo(trackId);
	}

	private void initTrackStat(Long trackId,String statType) {
		TrackStat trackStat = new TrackStat();
		trackStat.setTrackId(trackId);
		trackStat.setStatType(statType);
		this.trackStatMapper.insert(trackStat);
	}
}
